﻿package net.wangit.jdbc.generator;

import net.wangit.MapList;
import net.wangit.Row;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.DBImplementor;
import net.wangit.jdbc.table.TableConfigurationException;
import net.wangit.jdbc.util.DBHelper;
import net.wangit.support.IncrementorStringCreator;
import net.wangit.util.Checker;
import net.wangit.util.ClassUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class Incrementor {

	private static Log log = LogFactory
			.getLog(net.wangit.jdbc.generator.Incrementor.class);
	private static final String SQL_FIND = "select * from INCREMENTOR where iid=?";
	private static final String SQL_UPDATE = "update INCREMENTOR set sd=? where iid=?";
	private String domain;
	private String id;
	private long increment;
	private int size;
	private long maxCount;
	private String prefix;
	private String suffix;
	private IncrementorStringCreator isc;
	private long current;
	private long count;

	protected Incrementor(String domain, String id) {
		this.domain = domain;
		this.id = id;
		init();
	}

	public synchronized String next() {
		if (count >= maxCount)
			reload();
		StringBuffer value = new StringBuffer(prefix);
		if (isc != null)
			value.append(isc.getPrefix());
		if (size > 0) {
			int gap = size - Long.toString(current).length();
			while (gap > 0) {
				value.append("0");
				gap--;				
			}
		}
		value.append(current);
		if (isc != null)
			value.append(isc.getSuffix());
		value.append(suffix);
		current += increment;
		count++;
		if (log.isDebugEnabled())
			log.debug((new StringBuilder("Incrementor: value=")).append(value)
					.append(",current=").append(current).append(",count=")
					.append(count).append(",maxCount=").append(maxCount)
					.toString());
		return value.toString();
	}

	private void reload() {
		DBImplementor db = null;
		try {
			db = DBHelper.newDomainDB(domain);
			MapList list = db.query(Incrementor.SQL_FIND, id, 2);
			long currentSeed = list.getRow(0).getLong("sd", 0L);
			String newSeed = Long.toString(currentSeed + maxCount * increment);
			db.execute(Incrementor.SQL_UPDATE, new String[] { newSeed, id },
					new int[] { 13, 2 });
			current = currentSeed;
			count = 0L;
			if (log.isDebugEnabled())
				log.debug((new StringBuilder("update Incrementor(")).append(id)
						.append(")'seed to ").append(newSeed).append(
								" successfully.").toString());
		} catch (Exception e) {
			log.error((new StringBuilder("Incrementor(")).append(id).append(
					")' reload failed:").toString(), e);
			throw new TableConfigurationException((new StringBuilder(
					"could not reload Incrementor: ")).append(domain).append(
					"/").append(id).toString(), e);
		} finally {
			DBHelper.close(db);
		}
	}

	private void init() {
		DB db = null;
		try {
			db = DBHelper.getDomainDB(domain);
			MapList list = db.query(Incrementor.SQL_FIND, id, 2);
			Row row = list.getRow(0);
			increment = row.getLong("i", 1L);
			size = row.getInt("i1", 0);
			maxCount = row.getLong("c", 100L);
			prefix = row.get("a", "");
			suffix = row.get("s", "");
			String stringCreator = row.get("x");
			if (!Checker.isEmpty(stringCreator))
				isc = (IncrementorStringCreator) ClassUtil.loadClass(
						stringCreator).newInstance();
			reload();
		} catch (Exception e) {
			throw new TableConfigurationException((new StringBuilder(
					"could not reload Incrementor: ")).append(domain).append(
					"/").append(id).toString(), e);
		}
	}

}
